<template>
  <div class="ansible-audit-container">
    <!-- 星空背景 -->
    <div class="starry-background">
      <div class="stars"></div>
      <div class="stars2"></div>
      <div class="stars3"></div>
    </div>

    <!-- 主要内容区域 -->
    <div class="audit-content">
      <!-- 页面标题 -->
      <div class="page-header glass-effect">
        <div class="header-content">
          <div class="title-section">
            <h1 class="page-title">
              <i class="fa fa-file-text"></i>
              Harbor审计日志
            </h1>
            <p class="page-subtitle">查看Harbor仓库的操作审计日志，包括用户操作、镜像推拉等记录</p>
          </div>
          <div class="stats-section">
            <div class="stat-card glass-effect">
              <div class="stat-number">{{ statistics?.total_logs || 0 }}</div>
              <div class="stat-label">日志总数</div>
            </div>
            <div class="stat-card glass-effect">
              <div class="stat-number">{{ statistics?.today_logs || 0 }}</div>
              <div class="stat-label">今日日志</div>
            </div>
            <div class="stat-card glass-effect">
              <div class="stat-number">{{ statistics?.error_logs || 0 }}</div>
              <div class="stat-label">错误日志</div>
            </div>
          </div>
        </div>
      </div>

      <!-- 操作按钮 -->
      <div class="search-filters glass-effect">
        <el-form inline class="search-form">
          <div class="form-left">
            <el-select v-model="selectedRegistry" placeholder="选择Harbor仓库" class="server-select">
              <el-option
                v-for="registry in harborRegistries"
                :key="registry.id"
                :label="registry.name"
                :value="registry.id"
              >
                <div class="registry-option">
                  <i class="fa fa-ship"></i>
                  <span>{{ registry.name }}</span>
                  <span class="registry-url">({{ registry.url }})</span>
                </div>
              </el-option>
            </el-select>
            <el-select v-model="selectedLogLevel" placeholder="日志级别" class="server-select">
              <el-option label="全部" value="" />
              <el-option label="信息" value="info" />
              <el-option label="警告" value="warning" />
              <el-option label="错误" value="error" />
            </el-select>
            <el-date-picker
              v-model="dateRange"
              type="datetimerange"
              range-separator="至"
              start-placeholder="开始时间"
              end-placeholder="结束时间"
              class="date-picker"
            />
          </div>
          <div class="form-right">
            <el-button type="primary" @click="refreshLogs" class="glass-button refresh-button" :loading="loading">
              <i class="fa fa-refresh"></i>
              刷新日志
            </el-button>
            <el-button @click="exportLogs" class="glass-button sync-button">
              <i class="fa fa-download"></i>
              导出日志
            </el-button>
            <el-button @click="clearLogs" class="glass-button delete-button">
              <i class="fa fa-trash"></i>
              清理日志
            </el-button>
          </div>
        </el-form>
      </div>

      <!-- 日志列表 -->
      <div class="audit-table-section glass-effect">
        <div class="section-title">
          <i class="fa fa-file-text"></i>
          Harbor审计日志列表
        </div>

        <el-table
          :data="logs"
          style="width: 100%"
          v-loading="loading"
          row-class-name="audit-row"
          class="audit-table"
        >
          <el-table-column prop="op_time" label="时间戳" min-width="140" show-overflow-tooltip>
            <template #default="scope">
              <span class="time-text">
                {{ formatTime(scope.row.op_time) }}
              </span>
            </template>
          </el-table-column>

          <el-table-column prop="username" label="用户名" min-width="120" show-overflow-tooltip>
            <template #default="scope">
              <div class="config-name">
                <i class="fa fa-user"></i>
                {{ scope.row.username }}
              </div>
            </template>
          </el-table-column>

          <el-table-column prop="resource" label="资源" min-width="200" show-overflow-tooltip>
            <template #default="scope">
              <span class="resource-text">
                {{ scope.row.resource }}
              </span>
            </template>
          </el-table-column>

          <el-table-column prop="resource_type" label="资源类型" min-width="100" show-overflow-tooltip>
            <template #default="scope">
              <el-tag type="" size="small">
                {{ scope.row.resource_type }}
              </el-tag>
            </template>
          </el-table-column>

          <el-table-column prop="operation" label="操作" min-width="80" show-overflow-tooltip>
            <template #default="scope">
              <el-tag :type="getOperationTagType(scope.row.operation)" size="small">
                {{ scope.row.operation }}
              </el-tag>
            </template>
          </el-table-column>

          <el-table-column prop="operation_description" label="Operation Description" min-width="200" show-overflow-tooltip>
            <template #default="scope">
              <span class="description-text">
                {{ scope.row.operation_description }}
              </span>
            </template>
          </el-table-column>

          <el-table-column prop="success" label="Success" min-width="80" show-overflow-tooltip>
            <template #default="scope">
              <el-tag :type="scope.row.success ? 'success' : 'danger'" size="small">
                {{ scope.row.success ? 'true' : 'false' }}
              </el-tag>
            </template>
          </el-table-column>



          <el-table-column label="操作" width="200" :show-overflow-tooltip="false">
            <template #default="scope">
              <div class="action-buttons">
                <el-button
                  @click="viewDetails(scope.row)"
                  size="small"
                  class="glass-button info-button action-btn"
                >
                  <i class="fa fa-info-circle"></i>
                  详情
                </el-button>
                <el-button
                  @click="viewContext(scope.row)"
                  size="small"
                  class="glass-button sync-button action-btn"
                >
                  <i class="fa fa-history"></i>
                  上下文
                </el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>

        <!-- 空状态 -->
        <div v-if="!loading && logs.length === 0" class="empty-state">
          <div class="empty-content">
            <i class="fa fa-file-text empty-icon"></i>
            <h3>暂无审计日志</h3>
            <p>请选择Harbor仓库和时间范围后刷新数据</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 审计日志详情对话框 -->
  <el-dialog
    v-model="detailDialogVisible"
    :title="detailDialogTitle"
    width="90%"
    top="5vh"
    class="glass-dialog inspect-dialog"
    destroy-on-close
  >
    <template #header="{ titleId, titleClass }">
      <div class="inspect-header">
        <div class="inspect-title">
          <i class="fa fa-info-circle inspect-icon"></i>
          <span :id="titleId" :class="titleClass">{{ detailDialogTitle }}</span>
        </div>
        <div class="inspect-controls">
          <el-button @click="copyDetailData" size="small" class="glass-button">
            <i class="fa fa-copy"></i>
            复制
          </el-button>
        </div>
      </div>
    </template>

    <div class="inspect-container">
      <div class="inspect-content" ref="detailContentRef">
        <div class="detail-sections">
          <!-- 基本信息 -->
          <div class="detail-section">
            <h4><i class="fa fa-info-circle"></i>基本信息</h4>
            <div class="detail-grid">
              <div class="detail-item">
                <label>日志ID:</label>
                <span class="detail-value">{{ currentDetailLog?.id || '-' }}</span>
              </div>
              <div class="detail-item">
                <label>操作时间:</label>
                <span class="detail-value">{{ formatTime(currentDetailLog?.op_time) || '-' }}</span>
              </div>
              <div class="detail-item">
                <label>操作用户:</label>
                <span class="detail-value user-name">
                  <i class="fa fa-user"></i>
                  {{ currentDetailLog?.username || '-' }}
                </span>
              </div>
              <div class="detail-item">
                <label>执行结果:</label>
                <span :class="['detail-value', 'status-badge', currentDetailLog?.success ? 'success' : 'failed']">
                  <i :class="['fa', currentDetailLog?.success ? 'fa-check-circle' : 'fa-times-circle']"></i>
                  {{ currentDetailLog?.success ? '成功' : '失败' }}
                </span>
              </div>
            </div>
          </div>

          <!-- 操作信息 -->
          <div class="detail-section">
            <h4><i class="fa fa-cogs"></i>操作信息</h4>
            <div class="detail-grid">
              <div class="detail-item">
                <label>操作类型:</label>
                <span class="detail-value operation-type">
                  <i class="fa fa-play-circle"></i>
                  {{ currentDetailLog?.operation || '-' }}
                </span>
              </div>
              <div class="detail-item">
                <label>资源类型:</label>
                <span class="detail-value resource-type">
                  <i class="fa fa-cube"></i>
                  {{ currentDetailLog?.resource_type || '-' }}
                </span>
              </div>
              <div class="detail-item full-width">
                <label>操作描述:</label>
                <span class="detail-value description">
                  {{ currentDetailLog?.operation_description || '-' }}
                </span>
              </div>
              <div class="detail-item full-width">
                <label>目标资源:</label>
                <span class="detail-value resource-path">
                  <i class="fa fa-link"></i>
                  {{ currentDetailLog?.resource || '-' }}
                </span>
              </div>
            </div>
          </div>

          <!-- 原始数据 -->
          <div class="detail-section">
            <h4><i class="fa fa-code"></i>原始数据 (JSON)</h4>
            <pre class="json-content">{{ JSON.stringify(currentDetailLog, null, 2) }}</pre>
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="inspect-footer">
        <div class="inspect-info">
          <span class="inspect-tip">
            <i class="fa fa-info-circle"></i>
            Harbor审计日志详细信息（JSON格式）
          </span>
        </div>
        <div class="inspect-actions">
          <el-button @click="scrollDetailToTop" class="glass-button">
            <i class="fa fa-arrow-up"></i>
            顶部
          </el-button>
          <el-button @click="scrollDetailToBottom" class="glass-button">
            <i class="fa fa-arrow-down"></i>
            底部
          </el-button>
          <el-button @click="closeDetailDialog" class="glass-button danger">
            <i class="fa fa-times"></i>
            关闭
          </el-button>
        </div>
      </div>
    </template>
  </el-dialog>

  <!-- 审计日志上下文对话框 -->
  <el-dialog
    v-model="contextDialogVisible"
    :title="contextDialogTitle"
    width="90%"
    top="5vh"
    class="glass-dialog inspect-dialog"
    destroy-on-close
  >
    <template #header="{ titleId, titleClass }">
      <div class="inspect-header">
        <div class="inspect-title">
          <i class="fa fa-history inspect-icon"></i>
          <span :id="titleId" :class="titleClass">{{ contextDialogTitle }}</span>
        </div>
        <div class="inspect-controls">
          <el-button @click="copyContextData" size="small" class="glass-button">
            <i class="fa fa-copy"></i>
            复制
          </el-button>
        </div>
      </div>
    </template>

    <div class="inspect-container">
      <div class="inspect-content" ref="contextContentRef">
        <div class="context-sections">
          <!-- 上下文信息 -->
          <div class="detail-section">
            <h4><i class="fa fa-info-circle"></i>上下文信息</h4>
            <div class="context-info">
              <div class="info-item">
                <i class="fa fa-user"></i>
                <span>用户: <strong>{{ currentContextLog?.username }}</strong></span>
              </div>
              <div class="info-item">
                <i class="fa fa-clock-o"></i>
                <span>时间范围: 30分钟内</span>
              </div>
              <div class="info-item">
                <i class="fa fa-list"></i>
                <span>相关操作: {{ contextLogs.length }} 条</span>
              </div>
            </div>
          </div>

          <!-- 操作时间线 -->
          <div class="detail-section">
            <h4><i class="fa fa-history"></i>操作时间线</h4>
            <div class="timeline-container">
              <div v-if="contextLogs.length === 0" class="no-context">
                <i class="fa fa-info-circle"></i>
                <span>未找到相关的上下文操作记录</span>
              </div>

              <div v-for="(contextLog, index) in contextLogs" :key="index"
                   :class="['timeline-item', { 'current': contextLog.id === currentContextLog?.id }]">
                <div class="timeline-marker">
                  <i :class="['fa', getOperationIcon(contextLog.operation)]"></i>
                </div>
                <div class="timeline-content">
                  <div class="timeline-header">
                    <div class="header-row-1">
                      <span class="operation-name">{{ contextLog.operation }}</span>
                      <span class="timeline-time">{{ formatTime(contextLog.op_time) }}</span>
                    </div>
                    <div class="header-row-2">
                      <span class="resource-type-badge">{{ contextLog.resource_type }}</span>
                    </div>
                  </div>
                  <div class="timeline-body">
                    <div class="resource-info">
                      <i class="fa fa-cube"></i>
                      <span>{{ contextLog.resource }}</span>
                    </div>
                    <div v-if="contextLog.operation_description" class="operation-desc">
                      {{ contextLog.operation_description }}
                    </div>
                    <div class="status-info">
                      <span :class="['status-indicator', contextLog.success ? 'success' : 'failed']">
                        <i :class="['fa', contextLog.success ? 'fa-check' : 'fa-times']"></i>
                        {{ contextLog.success ? '成功' : '失败' }}
                      </span>
                    </div>
                  </div>
                  <div v-if="contextLog.id === currentContextLog?.id" class="current-indicator">
                    <i class="fa fa-arrow-left"></i>
                    当前查看的日志
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="inspect-footer">
        <div class="inspect-info">
          <span class="inspect-tip">
            <i class="fa fa-history"></i>
            用户操作上下文记录
          </span>
        </div>
        <div class="inspect-actions">
          <el-button @click="scrollContextToTop" class="glass-button">
            <i class="fa fa-arrow-up"></i>
            顶部
          </el-button>
          <el-button @click="scrollContextToBottom" class="glass-button">
            <i class="fa fa-arrow-down"></i>
            底部
          </el-button>
          <el-button @click="closeContextDialog" class="glass-button danger">
            <i class="fa fa-times"></i>
            关闭
          </el-button>
        </div>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { dockerRegistryAPI } from '@/api/docker'
import { ElMessage, ElMessageBox } from 'element-plus'
import { nextTick, onMounted, reactive, ref, watch } from 'vue'

// 响应式数据
const loading = ref(false)
const selectedRegistry = ref('')
const selectedLogLevel = ref('')
const dateRange = ref([])
const harborRegistries = ref([])
const logs = ref([])

// 统计数据
const statistics = reactive({
  total_logs: 0,
  today_logs: 0,
  error_logs: 0
})

// 详情弹窗相关
const detailDialogVisible = ref(false)
const detailDialogTitle = ref('')
const detailContent = ref('')
const detailContentRef = ref()
const currentDetailLog = ref(null)

// 上下文弹窗相关
const contextDialogVisible = ref(false)
const contextDialogTitle = ref('')
const contextContent = ref('')
const contextContentRef = ref()
const currentContextLog = ref(null)
const contextLogs = ref([])

// 页面加载
onMounted(() => {
  loadData()
})

// 监听仓库选择变化
watch(selectedRegistry, async (newValue) => {
  if (newValue) {
    await Promise.all([
      loadAuditLogs(),
      loadStatistics()
    ])
  }
})

// 加载数据
const loadData = async () => {
  loading.value = true
  try {
    await loadHarborRegistries()
    if (selectedRegistry.value) {
      await Promise.all([
        loadAuditLogs(),
        loadStatistics()
      ])
    }
  } catch (error) {
    console.error('加载数据失败:', error)
    ElMessage.error('加载数据失败')
  } finally {
    loading.value = false
  }
}

// 加载Harbor仓库列表
const loadHarborRegistries = async () => {
  try {
    console.log('🔄 开始加载Harbor仓库列表...')
    const response = await dockerRegistryAPI.getRegistries()
    console.log('📦 API响应:', response)
    const allRegistries = response.data.results || response.data || []
    harborRegistries.value = allRegistries.filter((registry: any) =>
      registry.registry_type === 'harbor' && registry.is_active
    )
    console.log('✅ Harbor仓库列表加载完成:', harborRegistries.value)

    // 如果有仓库且没有选中的仓库，默认选择第一个
    if (harborRegistries.value.length > 0 && !selectedRegistry.value) {
      selectedRegistry.value = harborRegistries.value[0].id
    }
  } catch (error) {
    console.error('❌ 加载Harbor仓库失败:', error)
    ElMessage.error('加载Harbor仓库失败')
  }
}

// 加载审计日志
const loadAuditLogs = async () => {
  if (!selectedRegistry.value) return

  try {
    const params: any = {
      page: 1,
      page_size: 50
    }

    // 添加过滤条件
    if (selectedLogLevel.value) {
      params.operation = selectedLogLevel.value
    }

    if (dateRange.value && dateRange.value.length === 2) {
      params.start_time = new Date(dateRange.value[0]).toISOString()
      params.end_time = new Date(dateRange.value[1]).toISOString()
    }

    console.log('🔄 开始加载审计日志...', params)
    const response = await dockerRegistryAPI.getHarborAuditLogs(selectedRegistry.value, params)
    console.log('📦 审计日志响应:', response)

    if (response.data.success) {
      const rawLogs = response.data.data || []
      // 确保按时间戳倒序排列，最新的在最上面（精确到毫秒）
      logs.value = rawLogs.sort((a, b) => {
        // 使用完整的ISO时间戳进行排序，精确到毫秒
        const timeA = new Date(a.op_time).getTime()
        const timeB = new Date(b.op_time).getTime()

        // 如果时间相同，则按ID倒序
        if (timeB === timeA) {
          return (b.id || 0) - (a.id || 0)
        }

        return timeB - timeA // 倒序排列
      })
      console.log('✅ 审计日志加载完成:', logs.value.length, '条，已按时间倒序排列')
    } else {
      ElMessage.error(response.data.message || '加载审计日志失败')
    }
  } catch (error) {
    console.error('❌ 加载审计日志失败:', error)
    ElMessage.error('加载审计日志失败')
  }
}

// 加载统计信息
const loadStatistics = async () => {
  if (!selectedRegistry.value) return

  try {
    console.log('🔄 开始加载统计信息...')
    const response = await dockerRegistryAPI.getHarborAuditLogStatistics(selectedRegistry.value)
    console.log('📊 统计信息响应:', response)

    if (response.data.success) {
      Object.assign(statistics, response.data.data)
      console.log('✅ 统计信息加载完成:', statistics)
    } else {
      ElMessage.error(response.data.message || '加载统计信息失败')
    }
  } catch (error) {
    console.error('❌ 加载统计信息失败:', error)
    ElMessage.error('加载统计信息失败')
  }
}

// 刷新日志
const refreshLogs = async () => {
  if (!selectedRegistry.value) {
    ElMessage.warning('请先选择Harbor仓库')
    return
  }

  loading.value = true
  try {
    await Promise.all([
      loadAuditLogs(),
      loadStatistics()
    ])
    ElMessage.success('日志刷新成功')
  } catch (error) {
    console.error('刷新日志失败:', error)
    ElMessage.error('刷新日志失败')
  } finally {
    loading.value = false
  }
}

// 导出日志
const exportLogs = async () => {
  if (!selectedRegistry.value) {
    ElMessage.warning('请先选择Harbor仓库')
    return
  }

  try {
    const params: any = {}

    // 添加过滤条件
    if (selectedLogLevel.value) {
      params.operation = selectedLogLevel.value
    }

    if (dateRange.value && dateRange.value.length === 2) {
      params.start_time = new Date(dateRange.value[0]).toISOString()
      params.end_time = new Date(dateRange.value[1]).toISOString()
    }

    ElMessage.info('正在导出日志，请稍候...')
    const response = await dockerRegistryAPI.exportHarborAuditLogs(selectedRegistry.value, params)

    // 创建下载链接
    const blob = new Blob([response.data], { type: 'application/json' })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url

    // 生成文件名
    const timestamp = new Date().toISOString().slice(0, 19).replace(/[:-]/g, '')
    const registryName = harborRegistries.value.find(r => r.id === selectedRegistry.value)?.name || 'harbor'
    link.download = `harbor_audit_logs_${registryName}_${timestamp}.json`

    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)

    ElMessage.success('日志导出成功')
  } catch (error) {
    console.error('导出日志失败:', error)
    ElMessage.error('导出日志失败')
  }
}

// 清理日志
const clearLogs = async () => {
  if (!selectedRegistry.value) {
    ElMessage.warning('请先选择Harbor仓库')
    return
  }

  try {
    await ElMessageBox.confirm(
      '确定要清理Harbor审计日志吗？此操作将清理30天前的日志记录。',
      '确认清理',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        customClass: 'glass-dialog'
      }
    )

    const response = await dockerRegistryAPI.clearHarborAuditLogs(selectedRegistry.value, 30)

    if (response.data.success) {
      ElMessage.success(response.data.message)
      await refreshLogs()
    } else {
      ElMessage.error(response.data.message || '清理日志失败')
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('清理日志失败:', error)
      ElMessage.error('清理日志失败')
    }
  }
}

// 查看详情
const viewDetails = async (log: any) => {
  try {
    // 保存当前日志信息
    currentDetailLog.value = log

    // 显示详情对话框
    detailDialogVisible.value = true
    detailDialogTitle.value = `Harbor审计日志 ${log.id} 详细信息`

    // 格式化JSON显示
    detailContent.value = JSON.stringify(log, null, 2)

    // 等待DOM更新后滚动到顶部
    nextTick(() => {
      scrollDetailToTop()
    })
  } catch (error) {
    ElMessage.error('显示详情失败')
  }
}

// 查看上下文
const viewContext = async (log: any) => {
  try {
    // 保存当前日志信息
    currentContextLog.value = log

    // 获取相同用户在相近时间的操作记录
    contextLogs.value = logs.value.filter(l => {
      const logTime = new Date(l.op_time).getTime()
      const currentTime = new Date(log.op_time).getTime()
      const timeDiff = Math.abs(logTime - currentTime)
      return l.username === log.username && timeDiff <= 30 * 60 * 1000 // 30分钟内
    }).sort((a, b) => {
      // 按时间倒序排列，最新的在最上面
      const timeA = new Date(a.op_time).getTime()
      const timeB = new Date(b.op_time).getTime()
      return timeB - timeA
    })

    // 显示上下文对话框
    contextDialogVisible.value = true
    contextDialogTitle.value = `操作上下文 - ${log.username}`

    // 等待DOM更新后滚动到顶部
    nextTick(() => {
      scrollContextToTop()
    })
  } catch (error) {
    ElMessage.error('显示上下文失败')
  }
}

// 详情弹窗相关函数
const copyDetailData = async () => {
  try {
    await navigator.clipboard.writeText(detailContent.value)
    ElMessage.success('详情数据已复制到剪贴板')
  } catch (error) {
    ElMessage.error('复制失败')
  }
}

const scrollDetailToTop = () => {
  if (detailContentRef.value) {
    detailContentRef.value.scrollTop = 0
  }
}

const scrollDetailToBottom = () => {
  if (detailContentRef.value) {
    detailContentRef.value.scrollTop = detailContentRef.value.scrollHeight
  }
}

const closeDetailDialog = () => {
  detailDialogVisible.value = false
  currentDetailLog.value = null
  detailContent.value = ''
}

// 上下文弹窗相关函数
const copyContextData = async () => {
  try {
    await navigator.clipboard.writeText(contextContent.value)
    ElMessage.success('上下文数据已复制到剪贴板')
  } catch (error) {
    ElMessage.error('复制失败')
  }
}

const scrollContextToTop = () => {
  if (contextContentRef.value) {
    contextContentRef.value.scrollTop = 0
  }
}

const scrollContextToBottom = () => {
  if (contextContentRef.value) {
    contextContentRef.value.scrollTop = contextContentRef.value.scrollHeight
  }
}

const closeContextDialog = () => {
  contextDialogVisible.value = false
  currentContextLog.value = null
  contextContent.value = ''
  contextLogs.value = []
}

// 获取操作图标
const getOperationIcon = (operation: string) => {
  const iconMap = {
    'create': 'fa-plus-circle',
    'delete': 'fa-trash',
    'push': 'fa-upload',
    'pull': 'fa-download',
    'scan': 'fa-search',
    'update': 'fa-edit',
    'login': 'fa-sign-in',
    'logout': 'fa-sign-out'
  }
  return iconMap[operation] || 'fa-circle'
}

// 格式化时间
const formatTime = (timeStr: string) => {
  if (!timeStr) return '-'
  try {
    const date = new Date(timeStr)
    return date.toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit'
    })
  } catch (error) {
    return timeStr
  }
}

// 获取操作标签类型
const getOperationTagType = (operation: string) => {
  const typeMap: Record<string, string> = {
    'push': 'success',
    'pull': 'info',
    'delete': 'danger',
    'create': 'success',
    'update': 'warning',
    'scan': 'warning'
  }
  return typeMap[operation] || 'info'
}

// 获取日志级别标签类型
const getLogLevelTagType = (level: string) => {
  const typeMap: Record<string, string> = {
    'info': 'info',
    'warning': 'warning',
    'error': 'danger'
  }
  return typeMap[level] || 'info'
}
</script>

<style scoped>
/* 使用与Docker镜像管理页面完全相同的样式 */
.ansible-audit-container {
  min-height: 100vh;
  background: linear-gradient(
    135deg,
    rgba(0, 0, 0, 0.9) 0%,
    rgba(20, 20, 40, 0.95) 50%,
    rgba(0, 0, 0, 0.9) 100%
  );
  overflow-x: hidden;
}

/* 星空背景 */
.starry-background {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

.stars, .stars2, .stars3 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: transparent;
}

.stars {
  background-image:
    radial-gradient(2px 2px at 20px 30px, #eee, transparent),
    radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.8), transparent),
    radial-gradient(1px 1px at 90px 40px, #fff, transparent),
    radial-gradient(1px 1px at 130px 80px, rgba(255,255,255,0.6), transparent),
    radial-gradient(2px 2px at 160px 30px, #ddd, transparent);
  background-repeat: repeat;
  background-size: 200px 100px;
  animation: zoom 20s infinite linear;
}

.stars2 {
  background-image:
    radial-gradient(1px 1px at 40px 50px, #fff, transparent),
    radial-gradient(1px 1px at 90px 80px, rgba(255,255,255,0.8), transparent),
    radial-gradient(1px 1px at 130px 20px, #eee, transparent),
    radial-gradient(2px 2px at 160px 60px, rgba(255,255,255,0.6), transparent);
  background-repeat: repeat;
  background-size: 200px 120px;
  animation: zoom 40s infinite linear;
}

.stars3 {
  background-image:
    radial-gradient(1px 1px at 60px 90px, #fff, transparent),
    radial-gradient(1px 1px at 100px 40px, rgba(255,255,255,0.7), transparent),
    radial-gradient(2px 2px at 140px 70px, #eee, transparent);
  background-repeat: repeat;
  background-size: 250px 150px;
  animation: zoom 60s infinite linear;
}

@keyframes zoom {
  from { transform: scale(1); }
  to { transform: scale(1.5); }
}

.audit-content {
  position: relative;
  z-index: 1;
  padding: 24px;
}

.glass-effect {
  background: rgba(164, 244, 186, 0.1);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 12px;
  backdrop-filter: blur(20px);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.page-header {
  margin-bottom: 24px;
  padding: 24px;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
}

.title-section {
  flex: 1;
}

.page-title {
  font-size: 28px;
  font-weight: 700;
  color: #00eaff;
  margin: 0 0 8px 0;
  display: flex;
  align-items: center;
  gap: 12px;
}

.page-title i {
  color: #a4f4ba;
  font-size: 24px;
}

.page-subtitle {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.7);
  margin: 0;
  line-height: 1.5;
}

.stats-section {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.stat-card {
  min-width: 120px;
  padding: 16px 20px;
  text-align: center;
  transition: all 0.3s ease;
}

.stat-card:hover {
  background: rgba(164, 244, 186, 0.15);
  border-color: rgba(164, 244, 186, 0.3);
  transform: translateY(-2px);
}

.stat-number {
  font-size: 24px;
  font-weight: 700;
  color: #00eaff;
  margin-bottom: 4px;
  line-height: 1;
}

.stat-label {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.8);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  line-height: 1;
}

/* 搜索过滤器 */
.search-filters {
  margin-bottom: 24px;
  padding: 20px;
}

.search-form {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}

.form-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

.form-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.server-select {
  min-width: 200px;
}

.date-picker {
  min-width: 300px;
}

.registry-option {
  display: flex;
  align-items: center;
  gap: 8px;
}

.registry-option i {
  color: #a4f4ba;
}

.registry-url {
  color: rgba(255, 255, 255, 0.6);
  font-size: 12px;
}

/* 审计表格区域 */
.audit-table-section {
  margin-bottom: 24px;
  overflow: hidden;
}

.section-title {
  font-size: 18px;
  font-weight: 600;
  color: #00eaff;
  margin-bottom: 20px;
  padding: 0 24px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-title i {
  color: #a4f4ba;
}

/* 审计表格样式 */
.audit-table {
  background: transparent !important;
}

.audit-table :deep(.el-table__header) {
  background: rgba(164, 244, 186, 0.05) !important;
}

.audit-table :deep(.el-table__header th) {
  background: transparent !important;
  border-bottom: 1px solid rgba(164, 244, 186, 0.2) !important;
  color: #00eaff !important;
  font-weight: 600 !important;
  padding: 16px 12px !important;
}

.audit-table :deep(.el-table__body tr) {
  background: transparent !important;
  transition: all 0.3s ease !important;
}

.audit-table :deep(.el-table__body tr:hover) {
  background: rgba(164, 244, 186, 0.05) !important;
}

.audit-table :deep(.el-table__body td) {
  border-bottom: 1px solid rgba(164, 244, 186, 0.1) !important;
  color: rgba(255, 255, 255, 0.9) !important;
  padding: 16px 12px !important;
}

.audit-row {
  transition: all 0.3s ease;
}

.audit-row:hover {
  background: rgba(164, 244, 186, 0.05) !important;
}

/* 配置名称样式 */
.config-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
}

.config-name i {
  color: #a4f4ba;
  font-size: 14px;
}

/* 时间文本样式 */
.time-text {
  color: rgba(255, 255, 255, 0.8);
  font-size: 12px;
  font-family: 'Courier New', monospace;
}

/* 资源文本样式 */
.resource-text {
  color: #a4f4ba;
  font-weight: 500;
}

/* IP文本样式 */
.ip-text {
  color: #00eaff;
  font-family: 'Courier New', monospace;
  font-size: 12px;
}

/* 操作按钮样式 */
.action-buttons {
  display: flex;
  gap: 6px;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-start;
}

.action-btn {
  min-width: 70px !important;
  white-space: nowrap;
  padding: 4px 8px !important;
  font-size: 12px !important;
}



/* 详情对话框样式 - 与Docker容器管理一致 */
.inspect-dialog {
  --el-dialog-bg-color: rgba(26, 26, 26, 0.95);
  --el-dialog-border-radius: 12px;
}

.inspect-dialog .el-dialog__header {
  padding: 0;
  border-bottom: 1px solid rgba(164, 244, 186, 0.2);
}

.inspect-dialog .el-dialog__body {
  padding: 0;
  background: #0a0a0a;
}

.inspect-dialog .el-dialog__footer {
  padding: 0;
  border-top: 1px solid rgba(164, 244, 186, 0.2);
}

.inspect-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 24px;
  background: rgba(164, 244, 186, 0.1);
  border-radius: 12px 12px 0 0;
}

.inspect-title {
  display: flex;
  align-items: center;
  gap: 12px;
  color: #ffffff;
  font-size: 18px;
  font-weight: 600;
}

.inspect-icon {
  color: #a4f4ba;
  font-size: 20px;
}

.inspect-controls {
  display: flex;
  gap: 8px;
}

.inspect-container {
  height: 70vh;
  max-height: 600px;
  overflow: hidden;
  background: #0a0a0a;
}

.inspect-content {
  height: 100%;
  overflow-y: auto;
  padding: 0;
}

.inspect-text {
  background: #0a0a0a;
  color: #ffffff;
  font-family: 'Courier New', monospace;
  font-size: 13px;
  line-height: 1.5;
  margin: 0;
  padding: 20px;
  white-space: pre-wrap;
  word-wrap: break-word;
  border: none;
  outline: none;
}

.inspect-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background: rgba(164, 244, 186, 0.05);
  border-radius: 0 0 12px 12px;
}

.inspect-info {
  display: flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
}

.inspect-tip {
  display: flex;
  align-items: center;
  gap: 6px;
}

.inspect-actions {
  display: flex;
  gap: 8px;
}

/* 详情页面样式 */
.detail-sections {
  padding: 20px;
}

.detail-section {
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
}

.detail-section h4 {
  color: #a4f4ba;
  margin: 0 0 16px 0;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
}

.detail-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.detail-item.full-width {
  grid-column: 1 / -1;
}

.detail-item label {
  color: rgba(255, 255, 255, 0.7);
  font-size: 13px;
  font-weight: 500;
}

.detail-value {
  color: #ffffff;
  font-size: 14px;
  word-break: break-all;
  display: flex;
  align-items: center;
  gap: 6px;
}

.user-name {
  color: #a4f4ba;
}

.operation-type {
  color: #00eaff;
}

.resource-type {
  color: #ffd700;
}

.resource-path {
  color: #ff9500;
  font-family: 'Courier New', monospace;
}

.description {
  color: rgba(255, 255, 255, 0.9);
  font-style: italic;
}

.status-badge {
  padding: 4px 8px;
  border-radius: 4px;
  font-weight: bold;
  font-size: 12px;
}

.status-badge.success {
  background: rgba(103, 194, 58, 0.2);
  color: #67c23a;
}

.status-badge.failed {
  background: rgba(245, 108, 108, 0.2);
  color: #f56c6c;
}

.json-content {
  background: rgba(0, 0, 0, 0.6);
  color: #ffffff;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  line-height: 1.4;
  padding: 16px;
  border-radius: 6px;
  margin: 0;
  max-height: 300px;
  overflow-y: auto;
  border: 1px solid rgba(164, 244, 186, 0.3);
}

/* 上下文页面样式 */
.context-sections {
  padding: 20px;
}

.context-info {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  padding: 16px;
  background: rgba(0, 234, 255, 0.1);
  border-radius: 6px;
  border: 1px solid rgba(0, 234, 255, 0.3);
}

.info-item {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #ffffff;
  font-size: 14px;
}

.info-item i {
  color: #00eaff;
}

.timeline-container {
  max-height: 500px;
  overflow-y: auto;
  padding: 16px;
  padding-right: 24px;
}

.no-context {
  text-align: center;
  padding: 60px 20px;
  color: rgba(255, 255, 255, 0.6);
  font-size: 16px;
}

.no-context i {
  margin-right: 12px;
  color: #a4f4ba;
  font-size: 18px;
}

.timeline-item {
  display: flex;
  margin-bottom: 24px;
  position: relative;
  min-height: 80px;
}

.timeline-item.current {
  background: rgba(0, 234, 255, 0.1);
  border-radius: 12px;
  padding: 16px;
  margin: 16px 0;
  border: 1px solid rgba(0, 234, 255, 0.3);
}

.timeline-marker {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(164, 244, 186, 0.2);
  border: 2px solid #a4f4ba;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 20px;
  flex-shrink: 0;
  margin-top: 4px;
}

.timeline-item.current .timeline-marker {
  background: rgba(0, 234, 255, 0.3);
  border-color: #00eaff;
  width: 44px;
  height: 44px;
}

.timeline-marker i {
  color: #a4f4ba;
  font-size: 16px;
}

.timeline-item.current .timeline-marker i {
  color: #00eaff;
  font-size: 18px;
}

.timeline-content {
  flex: 1;
  min-width: 0;
  padding: 4px 0;
}

.timeline-header {
  margin-bottom: 12px;
}

.timeline-header .header-row-1 {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}

.timeline-header .header-row-2 {
  display: flex;
  align-items: center;
  gap: 8px;
}

.operation-name {
  color: #00eaff;
  font-weight: bold;
  font-size: 16px;
  flex: 1;
}

.timeline-time {
  color: rgba(255, 255, 255, 0.7);
  font-size: 13px;
  white-space: nowrap;
  flex-shrink: 0;
}

.resource-type-badge {
  background: rgba(164, 244, 186, 0.2);
  color: #a4f4ba;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  white-space: nowrap;
  flex-shrink: 0;
}

.timeline-body {
  margin-bottom: 12px;
  padding: 8px 0;
}

.resource-info {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  color: #ffffff;
  font-size: 14px;
  margin-bottom: 8px;
  word-break: break-all;
  line-height: 1.4;
  padding: 6px 0;
}

.resource-info i {
  color: #ffd700;
  flex-shrink: 0;
  margin-top: 2px;
}

.operation-desc {
  color: rgba(255, 255, 255, 0.8);
  font-size: 13px;
  font-style: italic;
  margin-bottom: 8px;
  line-height: 1.4;
  padding: 4px 0;
  word-break: break-word;
}

.status-info {
  display: flex;
  align-items: center;
  margin-top: 8px;
}

.status-indicator {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: bold;
  white-space: nowrap;
}

.status-indicator.success {
  background: rgba(103, 194, 58, 0.2);
  color: #67c23a;
  border: 1px solid rgba(103, 194, 58, 0.3);
}

.status-indicator.failed {
  background: rgba(245, 108, 108, 0.2);
  color: #f56c6c;
  border: 1px solid rgba(245, 108, 108, 0.3);
}

.current-indicator {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #00eaff;
  font-size: 13px;
  font-weight: bold;
  margin-top: 12px;
  padding: 8px 12px;
  background: rgba(0, 234, 255, 0.2);
  border-radius: 6px;
  border: 1px solid rgba(0, 234, 255, 0.4);
  white-space: nowrap;
}

/* 按钮样式 */
.glass-button {
  background: rgba(164, 244, 186, 0.15) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: rgba(255, 255, 255, 0.9) !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(10px) !important;
  border-radius: 8px !important;
  padding: 8px 16px !important;
  font-size: 14px !important;
}

.glass-button:hover {
  background: rgba(164, 244, 186, 0.25) !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  transform: translateY(-1px) !important;
}

.glass-button i {
  margin-right: 6px;
}

.refresh-button {
  background: rgba(0, 234, 255, 0.2) !important;
  border-color: rgba(0, 234, 255, 0.4) !important;
  color: #00eaff !important;
}

.refresh-button:hover {
  background: rgba(0, 234, 255, 0.3) !important;
  border-color: rgba(0, 234, 255, 0.6) !important;
}

.sync-button {
  background: rgba(155, 89, 182, 0.2) !important;
  border-color: rgba(155, 89, 182, 0.4) !important;
  color: #9b59b6 !important;
}

.sync-button:hover {
  background: rgba(155, 89, 182, 0.3) !important;
  border-color: rgba(155, 89, 182, 0.6) !important;
}

.delete-button {
  background: rgba(231, 76, 60, 0.2) !important;
  border-color: rgba(231, 76, 60, 0.4) !important;
  color: #e74c3c !important;
}

.delete-button:hover {
  background: rgba(231, 76, 60, 0.3) !important;
  border-color: rgba(231, 76, 60, 0.6) !important;
}

.info-button {
  background: rgba(52, 152, 219, 0.2) !important;
  border-color: rgba(52, 152, 219, 0.4) !important;
  color: #3498db !important;
}

.info-button:hover {
  background: rgba(52, 152, 219, 0.3) !important;
  border-color: rgba(52, 152, 219, 0.6) !important;
}

/* 空状态 */
.empty-state {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 400px;
  padding: 40px;
}

.empty-content {
  text-align: center;
}

.empty-icon {
  font-size: 64px;
  color: rgba(255, 255, 255, 0.3);
  margin-bottom: 16px;
}

.empty-content h3 {
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 8px;
  font-size: 18px;
}

.empty-content p {
  color: rgba(255, 255, 255, 0.6);
  margin: 0;
  font-size: 14px;
}

/* 日期选择器样式 - 优化可读性 */
.date-picker :deep(.el-input__wrapper) {
  background: rgba(255, 255, 255, 0.95) !important;
  border: 1px solid rgba(164, 244, 186, 0.5) !important;
  border-radius: 6px !important;
  backdrop-filter: blur(10px) !important;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
}

.date-picker :deep(.el-input__inner) {
  color: #333333 !important;
  background: transparent !important;
  font-weight: 500 !important;
}

.date-picker :deep(.el-input__inner::placeholder) {
  color: rgba(51, 51, 51, 0.6) !important;
}

.date-picker :deep(.el-input__prefix) {
  color: #a4f4ba !important;
}

.date-picker :deep(.el-input__suffix) {
  color: #a4f4ba !important;
}

.date-picker :deep(.el-input__wrapper:hover) {
  border-color: #a4f4ba !important;
  background: rgba(255, 255, 255, 1) !important;
}

.date-picker :deep(.el-input__wrapper.is-focus) {
  border-color: #00eaff !important;
  background: rgba(255, 255, 255, 1) !important;
  box-shadow: 0 0 0 2px rgba(0, 234, 255, 0.2) !important;
}

/* Element Plus 弹窗透明玻璃样式 */
:deep(.glass-message-box) {
  background: rgba(164, 244, 186, 0.1) !important;
  border: 1px solid rgba(164, 244, 186, 0.2) !important;
  border-radius: 12px !important;
  backdrop-filter: blur(20px) !important;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important;
}

:deep(.glass-message-box .el-message-box__header) {
  background: transparent !important;
  border-bottom: 1px solid rgba(164, 244, 186, 0.2) !important;
  padding: 20px 24px 16px !important;
}

:deep(.glass-message-box .el-message-box__title) {
  color: #00eaff !important;
  font-weight: 600 !important;
}

:deep(.glass-message-box .el-message-box__content) {
  background: transparent !important;
  color: rgba(255, 255, 255, 0.9) !important;
  padding: 16px 24px !important;
}

:deep(.glass-message-box .el-message-box__btns) {
  background: transparent !important;
  border-top: 1px solid rgba(164, 244, 186, 0.2) !important;
  padding: 16px 24px 20px !important;
}

:deep(.glass-message-box .el-button--primary) {
  background: linear-gradient(135deg, #00eaff 0%, #a4f4ba 100%) !important;
  border: none !important;
  color: #000 !important;
  font-weight: 600 !important;
  border-radius: 6px !important;
  transition: all 0.3s ease !important;
}

:deep(.glass-message-box .el-button--primary:hover) {
  background: linear-gradient(135deg, #00d4e6 0%, #8ee6a1 100%) !important;
  transform: translateY(-1px) !important;
  box-shadow: 0 4px 12px rgba(0, 234, 255, 0.3) !important;
}

:deep(.glass-message-box .el-button--default) {
  background: rgba(164, 244, 186, 0.1) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: rgba(255, 255, 255, 0.9) !important;
  border-radius: 6px !important;
  transition: all 0.3s ease !important;
}

:deep(.glass-message-box .el-button--default:hover) {
  background: rgba(164, 244, 186, 0.2) !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  transform: translateY(-1px) !important;
}

.date-picker :deep(.el-input__inner) {
  color: rgba(255, 255, 255, 0.9) !important;
  background: transparent !important;
}

.date-picker :deep(.el-input__inner::placeholder) {
  color: rgba(255, 255, 255, 0.5) !important;
}
</style>
